package com.tizona.dao.jdbc;

import com.tizona.dao.ContractDAO;
import com.tizona.entity.*;
import com.tizona.entity.tarification.Parameter;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.ResultSet;
import java.util.Calendar;
import java.util.Map;

/**
 * User: vit
 * Date: Aug 31, 2006
 * Time: 5:01:03 PM
 */
public class ContractDAOJdbc extends BaseDAOJdbc implements ContractDAO {

    private FastStatement fstmtAccumsCreate, fstmtAccumsUpdate, fstmtAccums
            ,fstmtParam, fstmtPropsUpdate, fstmtSePropsUpdate, fstmtPropsCreate, fstmtSePropsCreate;

    public void setRequest(SQLRequest req) throws SQLException {
        this.request = req;

        fstmtAccumsCreate = request.prepare("INSERT INTO LC_ACCUM (LC_Num,NAME,VALUE,LAST_UPDATE) values"+
                " (?,?,?,?)");

        fstmtAccumsUpdate = request.prepare("UPDATE LC_ACCUM SET VALUE=?, LAST_UPDATE=? "+
                "WHERE NAME=? AND LC_Num=?");

        fstmtAccums = request.prepare("SELECT NAME,VALUE,LAST_UPDATE FROM LC_ACCUM WHERE LC_Num=?");

        fstmtParam = request.prepare("SELECT 2 as SOURCE, NAME,VALUE,DATE FROM LC_PROPS WHERE LC_Num=? union select 1 as SOURCE, NAME,VALUE, null as DATE from TC_PROPS, LC where LC.TC_ID=TC_PROPS.TC_ID and LC_Num=? order by SOURCE");

        fstmtPropsUpdate = request.prepare("update LC_PROPS set VALUE = ?,DATE=? WHERE NAME=? and LC_Num=?");

        fstmtSePropsUpdate = request.prepare("update SE_PROPS set VALUE = ?,DATE=? WHERE NAME=? and SE_ID=?");

        fstmtPropsCreate = request.prepare("insert LC_PROPS (LC_Num,NAME,VALUE,DATE) values(?,?,?,?)");

        fstmtSePropsCreate = request.prepare("insert SE_PROPS (SE_ID,NAME,VALUE,DATE) values(?,?,?,?)");

    }

    public void updateAccumulators(Lc lc, final Calendar model_time) throws SQLException {

        for(Map.Entry element:lc.getLcAccum().entrySet()) {

            com.tizona.entity.tarification.Accumulator accum = (com.tizona.entity.tarification.Accumulator) element.getValue();

            if(accum.isChanged()) {
                String key = (String) element.getKey();
                if(accum.getLastupdate() == null) {

                    log.debug("Create ACCUMULATOR: " + key + " val=" + accum.getValue());

                    Timestamp lastUpdate = new Timestamp(model_time.getTimeInMillis());

                    fstmtAccumsCreate.setLong(1, lc.getLcNum());
                    fstmtAccumsCreate.setString(2, key);
                    fstmtAccumsCreate.setLong(3, accum.getValue());
                    fstmtAccumsCreate.setTimestamp(4, lastUpdate);
                    request.update(fstmtAccumsCreate);

                    accum.setLastupdate(lastUpdate);

                } else {

                    log.debug("Update ACCUMULATOR: " + key + " val=" + accum.getValue());

                    fstmtAccumsUpdate.setLong(1, accum.getValue());
                    fstmtAccumsUpdate.setTimestamp(2, new Timestamp(model_time.getTimeInMillis()));
                    fstmtAccumsUpdate.setString(3, key);
                    fstmtAccumsUpdate.setLong(4, lc.getLcNum());
                    request.update(fstmtAccumsUpdate);
                }

            }
        }
    }

    public void loadAccumulators(Lc lc) throws SQLException {
        fstmtAccums.setLong(1, lc.getLcNum());
        LcAccum lcaccum;
        for(ResultSet resultset = request.query(fstmtAccums); resultset.next(); lc.getLcAccum().put(resultset.getString("NAME"), lcaccum))
            lcaccum = new LcAccum(resultset.getLong("VALUE"), resultset.getTimestamp("LAST_UPDATE"));

    }

    public void loadParams(Lc lc) throws SQLException {
        fstmtParam.setLong(1, lc.getLcNum());
        fstmtParam.setLong(2, lc.getLcNum());
        LcProp lcprop;
        for(ResultSet resultset = request.query(fstmtParam); resultset.next(); lc.getLcProps().put(resultset.getString("NAME"), lcprop))
        {
            if (resultset.getString("VALUE") != null)
                lcprop = new LcProp(resultset.getString("VALUE"));
            else
                lcprop = new LcProp(resultset.getTimestamp("DATE"));
        }
    }

    public int createProp(Lc lc, String key, com.tizona.entity.tarification.Parameter param) throws SQLException {

        fstmtPropsCreate.setLong(1, lc.getLcNum());
        fstmtPropsCreate.setString(2, key);
        if(param.getDate()==null) {
            fstmtPropsCreate.setString(3, param.asString());
            fstmtPropsCreate.setNull(4, java.sql.Types.NUMERIC);
            log.debug("Create KEY: " + key + " VALUE: " + param.asString());
        }
        else {
            fstmtPropsCreate.setNull(3, java.sql.Types.NUMERIC);
            fstmtPropsCreate.setTimestamp(4, new Timestamp(param.getDate().getTime()));
            log.debug("Create KEY: " + key + " Date: " + param.getDate().getTime());
        }

        return request.update(fstmtPropsCreate);

    }

    public int createProp(Se se, String key, com.tizona.entity.tarification.Parameter param) throws SQLException {

        fstmtSePropsCreate.setLong(1, se.getSeId());
        fstmtSePropsCreate.setString(2, key);
        if(param.getDate()==null) {
            fstmtSePropsCreate.setString(3, param.asString());
            fstmtSePropsCreate.setNull(4, java.sql.Types.NUMERIC);
            log.debug("Create SE KEY: " + key + " VALUE: " + param.asString());
        }
        else {
            fstmtSePropsCreate.setNull(3, java.sql.Types.NUMERIC);
            fstmtSePropsCreate.setTimestamp(4, new Timestamp(param.getDate().getTime()));
            log.debug("Create SE KEY: " + key + " Date: " + param.getDate().getTime());
        }

        return request.update(fstmtSePropsCreate);

    }

    public int updateProp(Lc lc, String key, Parameter param) throws SQLException {

        if(param.getDate()==null) {
            fstmtPropsUpdate.setString(1, param.asString());
            fstmtPropsUpdate.setNull(2, java.sql.Types.NUMERIC);
            log.debug("Update KEY: " + key + " VALUE: " + param.asString());
        }
        else {
            fstmtPropsUpdate.setNull(1, java.sql.Types.NUMERIC);
            fstmtPropsUpdate.setTimestamp(2, new Timestamp(param.getDate().getTime()));
            log.debug("Update KEY: " + key + " Date: " + param.getDate().getTime());
        }
        fstmtPropsUpdate.setString(3, key);
        fstmtPropsUpdate.setLong(4, lc.getLcNum());

        return request.update(fstmtPropsUpdate);
    }

    public int updateProp(Se se, String key, Parameter param) throws SQLException {

        if(param.getDate()==null) {
            fstmtSePropsUpdate.setString(1, param.asString());
            fstmtSePropsUpdate.setNull(2, java.sql.Types.NUMERIC);
            log.debug("Update SE KEY: " + key + " VALUE: " + param.asString());
        }
        else {
            fstmtSePropsUpdate.setNull(1, java.sql.Types.NUMERIC);
            fstmtSePropsUpdate.setTimestamp(2, new Timestamp(param.getDate().getTime()));
            log.debug("Update SE KEY: " + key + " Date: " + param.getDate().getTime());
        }
        fstmtSePropsUpdate.setString(3, key);
        fstmtSePropsUpdate.setLong(4, se.getSeId());

        return request.update(fstmtSePropsUpdate);
    }

}
